// 防止头文件被重复包含
#pragma once
// 定义日志级别 INFO ERROR FATAL DEBUG
#include "noncopyable.h"
#include <cstring>

// 通过定义宏方便地使用日志类 LOGINFO("%d %s",arg1,arg2)
// snprintf 将格式化后的字符串写入到缓冲区中
// ## __VA_ARGS__ 用于处理可变参数宏
// 优化后的日志宏

#define LOG(level, format, ...)                                                \
  do {                                                                         \
    if (level >= Logger::instance().getLogLevel()) {                           \
      char buffer[1024];                                                       \
      snprintf(buffer, sizeof(buffer), format, ##__VA_ARGS__);                 \
      Logger::instance().log(buffer);                                          \
    }                                                                          \
  } while (0)

// 快捷宏
#define LOG_INFO(format, ...) LOG(INFO, format, ##__VA_ARGS__)
#define LOG_ERROR(format, ...) LOG(ERROR, format, ##__VA_ARGS__)
#define LOG_FATAL(format, ...) LOG(FATAL, format, ##__VA_ARGS__)

// debug信息太多，通过宏控制是否输出调试信息 通过 -DMUDEBUG 编译选项或代码中手动
// #define MUDEBUG
#ifdef MUDEBUG
#define LOG_DEBUG(format, ...) LOG(DEBUG, format, ##__VA_ARGS__)
#else
#define LOG_DEBUG(format, ...)
#endif

enum LogLevel {
  INFO,  // 普通信息
  ERROR, // 错误信息
  FATAL, // 致命错误 core信息
  DEBUG  // 调试信息
};

// 输出一个日志类-单例模式
class Logger : mymuduo::noncopyable // 继承自noncopyable类，禁止拷贝和赋值
{
public:
  // 获取日志唯一的示例对象
  static Logger &instance();
  // 设置日志级别
  void setlogLevel(int level);
  // 写日志
  void log(const char *message);
  // 获取当前日志级别
  int getLogLevel() const;

private:
  int logLevel_ = INFO; // 默认日志级别为INFO
  Logger(){};
};